//#define __COMPILE_DEBUG__
#define _GNU_SOURCE

#include <stdbool.h>
#include <search.h>
#include <string.h>
#include "zepto.h"
#include "internal.h"

// should be enough for hello world
#define DEFAULT_SYMBOL_HASH_SIZE 3000

static struct hsearch_data symbols;

/**
 * Initialize symbol hash.
 * @param n maximum number of symbol names
 * @return nonzero on success
 */

int sym_init(int n)
{
  int ret;

  memset(&symbols, 0, sizeof(symbols));

  ret = hcreate_r(n ? n : DEFAULT_SYMBOL_HASH_SIZE, &symbols);
  
  return !ret;
}

/**
 * Find or create symbol by name.
 * @param[in] name - string symbol name
 * @param[out] inserted - shows if symbol was already added
 * @return symbol or NULL 
 */

struct zepto *sym_intern(char *name, bool *inserted)
{
  int ret;
  ENTRY e, *r;
  struct zepto *sym;

  DEBUG("intern symbol: %s", name);

  e.key = name;
  ret = hsearch_r(e, ENTER, &r, &symbols);

  if(!ret) {
    ERROR("Symbol hash full.");
  }

  if(r->key != name) {
    *inserted = 0;
    DEBUG("already have it, \"%s\"", r->key);
    return (struct zepto *)r->data;
  } else {
    *inserted = 1;
    sym = zepto_alloc();
    sym->type = ZEPTO_SYMBOL;
    sym->data.symbol = name;
    r->data = sym;
  }

  return r->data;
}

/**
 * Find symbol by name.
 * @param[in] name - string symbol name
 * @return symbol or NULL 
 */

struct zepto *sym_lookup(const char *name)
{
  int ret;
  ENTRY e, *r;
  
  e.key = (char *)name;

  DEBUG("sym_lookup(\"%s\")", name);
  ret = hsearch_r(e, FIND, &r, &symbols);

  if(!ret) {
    DEBUG("fail");
    return NULL;
  }
  DEBUG("success, %p", r->data);

  return (struct zepto *)r->data;
}
